package game.combat;

import board.Tile;
import character.CharacterCombatControl;
import character.MyCharacter;
import character.ai.AILogicControl;
import com.jme3.app.state.AbstractAppState;
import game.DataStore;
import game.InputController;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import player.AIPlayer;

public class TurnAppState extends AbstractAppState {
    protected CombatAppState combatAppState;
    TurnInputHandler turnInput = new TurnInputHandler();
    protected List<CombatActor> combatActors = new LinkedList<CombatActor>();
    protected ListIterator<CombatActor> combatActorIterator;
    protected CombatActor currentCombatActor;
    protected boolean turnSegmentFinished = false;

    @Deprecated
    protected TurnAppState() {}

    public TurnAppState(CombatAppState combatAppState) {
	this.combatAppState = combatAppState;
    }
    
    @Override
    public void setEnabled(boolean enabled) {
	super.setEnabled(enabled);
	if(enabled) {
	    turnSegmentFinished = false;
	    if(currentCombatActor instanceof MyCharacter && ((MyCharacter)currentCombatActor).getPlayer().equals(DataStore.player)) {
		InputController.setCurrentGameInput(turnInput);
	    }
	    startTurnSegment();
	}
    }

    @Override
    public void update(float tpf) {
	if(turnSegmentFinished) {
	    combatAppState.endCharacterTurnSegment();
	}
    }

    protected void startTurnSegment() {
        if(currentCombatActor.isFirstTurn()) {
            currentCombatActor.turnStarting();
            currentCombatActor.setFirstTurn(false);
        }
        if(currentCombatActor instanceof MyCharacter) {
            MyCharacter currentCharacter = (MyCharacter)currentCombatActor;
            if (currentCharacter.getControl(CharacterCombatControl.class).getTicksUsed() >= currentCharacter.getCharacterStatus().getTicksPerTurn()) {
                System.out.println(currentCharacter+" ran out of ticks. Ending turn.");
                endTurn();
            } else if(currentCharacter.getControl(CharacterCombatControl.class).getTicksUsed() == 0 && currentCharacter.getControl(CharacterCombatControl.class).hasQueuedAction()) {
                System.out.println("Resuming previous action for character: "+currentCharacter);
                turnSegmentFinished = true;
            } else {
                System.out.println("Starting turn segment for character: "+currentCharacter+" with initiative "+currentCharacter.getCharacterStatus().getInitiative());

                if(currentCharacter.getPlayer() instanceof AIPlayer) {
                    currentCharacter.getControl(AILogicControl.class).takeTurn();
                    if(currentCharacter.getControl(CharacterCombatControl.class).hasQueuedAction())
                        turnSegmentFinished = true;
                    else
                        endTurn();
                }
            }
        } else if(currentCombatActor instanceof Tile) {
            endTurn();
        }
    }

    public void endTurn() {
        currentCombatActor.setFirstTurn(true);
	if(!combatActorIterator.hasNext()) {
	    combatActorIterator = combatActors.listIterator();
	}
	currentCombatActor = combatActorIterator.next();
	combatAppState.turnEnded();
    }

    public Collection<CombatActor> getCombatActors() {
	return combatActors;
    }
    /** Orders all characters in initiative order. */
    public void setCombatActors(Collection<CombatActor> combatActors) {
	this.combatActors.clear();
	this.combatActors.addAll(combatActors);
        Collections.sort(this.combatActors, new CombatActorInitiativeComparator());
        resetIterator();
    }
    /** Reorders all characters in initiative order. */
    public void addCombatActor(CombatActor combatActor) {
        if(!combatActors.contains(combatActor)) {
            combatActorIterator.add(combatActor);
            Collections.sort(combatActors, new CombatActorInitiativeComparator());
            resetIteratorToCurrentPosition();
        }
    }
    public void removeCombatActor(CombatActor combatActor) {
        if(combatActor.equals(currentCombatActor)) {
            combatActorIterator.remove();
        } else {
	    combatActors.remove(combatActor);
	    resetIteratorToCurrentPosition();
	}
    }
    
    protected void resetIterator() {
        combatActorIterator = combatActors.listIterator();
        currentCombatActor = combatActorIterator.next();
    }
    protected void resetIteratorToCurrentPosition() {
        combatActorIterator = combatActors.listIterator();
        if(currentCombatActor != null && !combatActors.isEmpty()) {
            CombatActor pointer = combatActorIterator.next();
            while(!pointer.equals(currentCombatActor)) {
                pointer = combatActorIterator.next();
            }
        }
    }

    public CombatActor getCurrentCombatActor() {
	return currentCombatActor;
    }
}
